////////////////////////////////////////////////
// DESCRIPTION:
//     Class implementationn for device driver
//     access to installable ISR chaining
//
// Legal Notices:
//     Copyright (c) 2008, Telliam Consulting, LLC.
//     All rights reserved.
//
//     Redistribution and use in source and binary forms, with or without modification,
//     are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//
//     * Neither the name of Telliam Consulting nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// Disclaimer:
//     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//     IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
//     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
//     OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
//     OF THE POSSIBILITY OF SUCH DAMAGE.  
//
#include <windows.h>
#include <FusionWare\DFX\StreamAPI.h>

using namespace FusionWare::DFX;

ISRChainHandler::ISRChainHandler()
{
   this->hChainHandler = INVALID_HANDLE_VALUE;
}

bool ISRChainHandler::Load( const TCHAR* pIsrDll
                          , const TCHAR* pIsrHandler
                          , UINT32 SysIntr
                          , UINT32 Irq
                          , void* pIsrInfo     /*= NULL*/
                          , UINT32 IsrInfoSize /* =0*/)
{
    ASSERT(pIsrDll != NULL && pIsrHandler!=NULL && pIsrDll[0]!=TCHAR('\0') );

    // If something is loaded already, unload it. 
    Unload();

    this->hChainHandler = LoadIntChainHandler(pIsrDll, pIsrHandler, (BYTE)Irq);
    if(INVALID_HANDLE_VALUE == this->hChainHandler || NULL == this->hChainHandler)
        return false; 

    // --- ALL FAILURES after this point must Free the loaded chain.

    // pass the SYSINTR value to the handler
    if(IoControl(IOCTL_IISR_SYSINTR, &SysIntr, sizeof(SysIntr))) 
    {
        // if there is other ISRINFO needed pass it on as well
        if(IsrInfoSize!=0)
            return IoControl(IOCTL_IISR_INFO, pIsrInfo, IsrInfoSize);
        else
            return true;
    }

    // It didn't respond to the FusionWare IOCTL,
    // see if it responds to Microsoft's GIISR code.
    // To do that IsrInfo must be a GIISR_INFO structure
    //
    if(IsrInfoSize != sizeof(GIISR_INFO)) 
        return false;

    GIISR_INFO * giisrInfo = (GIISR_INFO*)(pIsrInfo);

    // fill in the sysIntr #
    giisrInfo->SysIntr = SysIntr;

    return IoControl(IOCTL_GIISR_INFO, pIsrInfo, IsrInfoSize);
}

/////////////////////////////////////////////////////////////////////
// Description:
//    Unloads the Insatllable ISR DLL if it was loaded.
//
// Returns:
//   TRUE if no error occured in the process.
//
// Comments:
//   Returns TRUE even if the RegInfo indicates no DLL to load
//
bool ISRChainHandler::Unload()
{
    if(INVALID_HANDLE_VALUE == this->hChainHandler)
        return true;

    // Save the handle to free it below
    HANDLE handler = this->hChainHandler;
    this->hChainHandler = INVALID_HANDLE_VALUE;
    return 0!=FreeIntChainHandler(handler);
}

